package co.gov.medellin.ssti.sub.model.dao.impl;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.dao.IncorrectResultSizeDataAccessException;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcDaoSupport;

import co.gov.medellin.ssti.sub.model.dao.SedeDAO;
import co.gov.medellin.ssti.sub.model.vo.SedeVO;
import co.gov.medellin.ssti.sub.model.vo.UsuarioxSedeVO;

public class SedeDAOImpl2 extends NamedParameterJdbcDaoSupport implements
		SedeDAO {

	private static final String SELECT_TODAS_SEDES = "SELECT codigo, UPPER(nombre) nombre FROM TCS_BEN_SEDE ORDER BY NOMBRE";

	public List<SedeVO> loadAllSedes() {

		List<SedeVO> sedes = getNamedParameterJdbcTemplate()
				.getJdbcOperations().query(SELECT_TODAS_SEDES,
						new RowMapper<SedeVO>() {

							public SedeVO mapRow(ResultSet rs, int rowNum)
									throws SQLException {
								SedeVO sede = new SedeVO();
								sede.setCodeSede(new Long(rs.getLong("codigo")));
								sede.setNombre(rs.getString("nombre"));
								return sede;
							}
						});
		return sedes;
	}

	public Collection<UsuarioxSedeVO> findUsuarioxSede(UsuarioxSedeVO criterea) {
		Map<String, Object> namedParameters = new HashMap<String, Object>();

		StringBuffer query = new StringBuffer(
				"SELECT usu.CODIGO codeusu, usu.NOMBRE nomusu, usu.DESCRIPCION descrip, prog.CODIGO codeprograma, "
						+ " prog.NOMBRE nomprograma, sub.CODIGO codesubprograma, sub.NOMBRE nomsubprograma, "
						+ " sede.CODIGO codesede, sede.NOMBRE nomsede, gus.descripcion descripGrupo "
						+ " FROM paoyer.tcs_usuario usu, paoyer.tcs_grupo_usuario gus,TCS_BEN_PROGRAMA prog, TCS_BEN_SUBPROGRAMA sub, "
						+ " TCS_BEN_SEDE sede, TCS_BEN_USUARIO_SEDE ususede, TCS_BEN_SUBPROGRAMA_SEDE subsede "
						+ " WHERE  ususede.SPSE_CODIGO = subsede.CODIGO AND subsede.SBPR_CODIGO = sub.CODIGO AND "
						+ " sub.PRG_CODIGO = prog.CODIGO AND subsede.SEDE_CODIGO = sede.CODIGO AND ususede.USU_CODIGO = usu.CODIGO "
						+ " AND usu.gus_codigo = gus.codigo AND sede.CODIGO = :sede.CODIGO ");

		namedParameters.put("sede.CODIGO", criterea.getCodeSede());

		if (criterea.getCodePrograma() != null) {
			query.append(" AND prog.CODIGO = :prog.CODIGO ");
			namedParameters.put("prog.CODIGO", criterea.getCodePrograma());
		}

		if (criterea.getCodeSubprograma() != null) {
			query.append(" AND sub.CODIGO = :sub.CODIGO ");
			namedParameters.put("sub.CODIGO", criterea.getCodeSubprograma());
		}

		List<UsuarioxSedeVO> Usuarios = getNamedParameterJdbcTemplate().query(
				query.toString(), namedParameters,
				new RowMapper<UsuarioxSedeVO>() {

					public UsuarioxSedeVO mapRow(ResultSet rs, int rowNum)
							throws SQLException {
						UsuarioxSedeVO usu = new UsuarioxSedeVO();
						usu.setNombreUsuario(rs.getString("nomusu"));
						usu.setCodeUsuario(rs.getLong("codeusu"));
						usu.setNombrePrograma(rs.getString("nomprograma"));
						usu.setNombreSubprograma(rs.getString("nomsubprograma"));
						usu.setDescripcionUsuario(rs.getString("descrip"));
						usu.setDescripcionGrupoUsuario(rs
								.getString("descripGrupo"));
						return usu;
					}
				});
		return Usuarios;
	}

	public Collection<SedeVO> findSedes(String nombreSede) {
		Map<String, Object> namedParameters = new HashMap<String, Object>();

		StringBuffer query = new StringBuffer(
				"SELECT codigo,nombre FROM TCS_BEN_SEDE ");
		if (!"".equals(nombreSede)) {
			query.append(" WHERE nombre like UPPER(:nombre) ");
			namedParameters.put("nombre", "%" + nombreSede.trim() + "%");
		}

		List<SedeVO> sedes = getNamedParameterJdbcTemplate().query(
				query.toString(), namedParameters, new RowMapper<SedeVO>() {

					public SedeVO mapRow(ResultSet rs, int rowNum)
							throws SQLException {
						SedeVO sede = new SedeVO();
						sede.setCode(new Long(rs.getString("codigo")));
						sede.setNombre(rs.getString("nombre"));
						return sede;
					}
				});
		return sedes;
	}

	public String findNameByCode(String strCodeSede) {
		Map<String, Object> namedParameters = new HashMap<String, Object>();

		String query = "SELECT nombre FROM TCS_BEN_SEDE WHERE codigo = :codigo ";

		String strName = null;

		namedParameters.put("codigo", strCodeSede);

		try {
			strName = getNamedParameterJdbcTemplate().queryForObject(query,
					namedParameters, String.class);
		} catch (IncorrectResultSizeDataAccessException e) {
			// TODO: handle exception
		}
		return strName;
	}

	// TODO: check usuCodigo
	public Collection<SedeVO> findTotalSedebyUser(Long codeUser,
			Long codeSubpro, String groupUserName, Long areaUser) {
		Map<String, Object> namedParameters = new HashMap<String, Object>();

		StringBuffer query = new StringBuffer(
				"SELECT distinct CODIGO, NOMBRE,CARACTER,DIRECCION_DESCRIPTIVA, "
						+ " DESDE_VIGENCIA,HASTA_VIGENCIA, VIGENCIA,CODNUCLEO, "
						+ " DESCNUCLEO, SEDE_CODIGO , DESCRIPCION, TIPO,DIRECCION_ENCASILLADA, "
						+ " LOCALIZACION_COBAMA,CODMUNI,DESCMUNI FROM VCS_BEN_SEDES ");

		if ((Object) codeUser != null && !groupUserName.equalsIgnoreCase("")) {

			query.append(" WHERE (codUser = usuCodigo OR 'ADMINISTRADOR GENERAL' = :groupUserName OR 'SUPER USUARIO' = :groupUserName OR codUser = :codeUser ");

			namedParameters.put("groupUserName", groupUserName);
			namedParameters.put("codeUser", codeUser);

			if (groupUserName != null
					&& groupUserName.equals("ADMINISTRADOR SECRETARIA")) {
				query.append(" OR COD_AREA = :COD_AREA ");
				namedParameters.put("COD_AREA", areaUser);
			}
			query.append(" ) ");

			if ((Object) codeSubpro != null) {
				query.append(" AND codSub = :codSub ");
				namedParameters.put("codSub", codeSubpro);
			}
		}

		List<SedeVO> lSede = getNamedParameterJdbcTemplate().query(
				query.toString(), namedParameters, new RowMapper<SedeVO>() {

					public SedeVO mapRow(ResultSet rst, int rowNum)
							throws SQLException {
						SedeVO sede = new SedeVO();
						sede.setCode(new Long(rst.getLong("CODIGO")));
						sede.setNombre(rst.getString("NOMBRE"));
						sede.setCaracter(rst.getString("CARACTER"));
						sede.setDireccion_descriptiva(rst
								.getString("DIRECCION_DESCRIPTIVA"));
						sede.setDesde(rst.getString("DESDE_VIGENCIA"));
						sede.setHasta(rst.getString("HASTA_VIGENCIA"));
						sede.setVigencia(rst.getString("VIGENCIA"));
						sede.setCodeNucleo(new Long(rst.getLong("CODNUCLEO")));
						sede.setDescNucleo(rst.getString("DESCNUCLEO"));
						sede.setCodeSubsede(new Long(rst.getLong("SEDE_CODIGO")));
						sede.setDescripcion(rst.getString("DESCRIPCION"));
						sede.setTipo(rst.getString("TIPO"));
						sede.setDireccion_encasillada(rst
								.getString("DIRECCION_ENCASILLADA"));
						sede.setLocalizacion_cobama(rst
								.getString("LOCALIZACION_COBAMA"));
						sede.setCodeMunicipio(new Long(rst.getLong("CODMUNI")));
						sede.setDescMunicipio(rst.getString("DESCMUNI"));
						return sede;
					}
				});
		return lSede;
	}

	public Collection<SedeVO> findTotalSedebyUser(Long codeUser,
			Long codeSubpro, String groupUserName, Long areaUser,
			String codeSede) {
		Map<String, Object> namedParameters = new HashMap<String, Object>();

		StringBuffer query = new StringBuffer("SELECT DISTINCT CODIGO, NOMBRE "
				+ " FROM VCS_BEN_SEDES ");

		if ((Object) codeUser != null && !groupUserName.equalsIgnoreCase("")) {
			query.append(" WHERE (codUser = usuCodigo OR 'ADMINISTRADOR GENERAL' = :groupUserName "
					+ " OR 'SUPER USUARIO' = :groupUserName OR codUser = :codeUser ");

			namedParameters.put("groupUserName", groupUserName);
			namedParameters.put("codeUser", codeUser);

			if (groupUserName != null
					&& groupUserName.equals("ADMINISTRADOR SECRETARIA")) {
				query.append(" OR COD_AREA = :COD_AREA ");
				namedParameters.put("COD_AREA", areaUser);
			}
			query.append(" ) ");

			if ((Object) codeSubpro != null) {
				query.append(" AND codSub = :codSub ");
				namedParameters.put("codSub", codeSubpro);
			}
		}

		final String codSede = codeSede;

		List<SedeVO> lSede = getNamedParameterJdbcTemplate().query(
				query.toString(), namedParameters, new RowMapper<SedeVO>() {

					public SedeVO mapRow(ResultSet rs, int rowNum)
							throws SQLException {
						SedeVO sede = new SedeVO();
						sede.setCode(rs.getLong("CODIGO"));
						sede.setNombre(rs.getString("NOMBRE"));
						return sede;
					}
				});

		boolean isSedeActual = false;
		for (SedeVO vo : lSede) {
			if (vo.getCode().equals(codSede)) {
				isSedeActual = true;
			}
		}

		if (!isSedeActual) {

			// limpiar query
			query.delete(0, query.length());

			query.append(" SELECT CODIGO, NOMBRE FROM TCS_BEN_SEDE "
					+ " WHERE CODIGO = :CODIGO ");

			// reusar map
			namedParameters.clear();
			namedParameters.put("CODIGO", codeSede);

			SedeVO sede = getNamedParameterJdbcTemplate().queryForObject(
					query.toString(), namedParameters, new RowMapper<SedeVO>() {

						public SedeVO mapRow(ResultSet rs, int rowNum)
								throws SQLException {
							SedeVO vo = new SedeVO();
							vo.setCode(rs.getLong("CODIGO"));
							vo.setNombre(rs.getString("NOMBRE"));
							return vo;
						}
					});

			lSede.add(sede);
		}

		return lSede;
	}

	public Collection<SedeVO> findSedesAsociadas(String codeSub) {
		Map<String, Object> namedParameters = new HashMap<String, Object>();

		String query = "SELECT DISTINCT sede.nombre NOMBRESEDE, TO_CHAR(sede.DESDE_VIGENCIA, 'yyyy-mm-dd') DESDE, "
				+ " TO_CHAR(sede.HASTA_VIGENCIA, 'yyyy-mm-dd') HASTA, decode(sede.VIGENCIA, 'A', 'S', 'I', 'N') VIGENCIASEDE "
				+ " FROM TCS_BEN_SEDE sede, TCS_BEN_SUBPROGRAMA_SEDE subsede "
				+ " WHERE subsede.SBPR_CODIGO = :SBPR_CODIGO "
				+ " AND subsede.SEDE_CODIGO = sede.CODIGO ";

		namedParameters.put("SBPR_CODIGO", codeSub);

		List<SedeVO> sedes = getNamedParameterJdbcTemplate().query(query,
				namedParameters, new RowMapper<SedeVO>() {

					public SedeVO mapRow(ResultSet rst, int rowNum)
							throws SQLException {
						SedeVO sedeVO = new SedeVO();
						sedeVO.setNombre(rst.getString("NOMBRESEDE"));
						sedeVO.setDesde(rst.getString("DESDE"));
						sedeVO.setHasta(rst.getString("HASTA"));
						sedeVO.setVigencia(rst.getString("VIGENCIASEDE"));
						return sedeVO;
					}
				});
		return sedes;
	}

	public Collection<SedeVO> findSedes() {
		String query = "SELECT codigo, upper(nombre) nombre FROM TCS_BEN_SEDE "
				+ " WHERE Fcs_Ben_Val_Vigencia(VIGENCIA, DESDE_VIGENCIA, HASTA_VIGENCIA, sysdate) = 'A' "
				+ " AND vigencia='A' ORDER BY nombre";

		List<SedeVO> lSede = getNamedParameterJdbcTemplate()
				.getJdbcOperations().query(query, new RowMapper<SedeVO>() {

					public SedeVO mapRow(ResultSet rst, int rowNum)
							throws SQLException {
						SedeVO sede = new SedeVO();
						sede.setCode(new Long(rst.getLong("CODIGO")));
						sede.setNombre(rst.getString("NOMBRE"));
						return sede;
					}
				});
		return lSede;
	}

	@Override
	public int desactivarSede(SedeVO sedeVO) {
		Map<String, Object> namedParameters = new HashMap<String, Object>();

		String strSql = " UPDATE  tcs_ben_sede set vigencia = 'I' ,"
				+ " USUARIO_MODIFICA = :USUARIO_MODIFICA, "
				+ " FECHA_MODIFICA = TO_DATE(:FECHA_MODIFICA,'dd/mm/yyyy'), "
				+ " TERMINAL_MODIFICA = :TERMINAL_MODIFICA WHERE CODIGO = :CODIGO ";

		namedParameters.put("USUARIO_MODIFICA", sedeVO.getUsuarioModifica());
		namedParameters.put("FECHA_MODIFICA", sedeVO.getFechaModifica());
		namedParameters.put("TERMINAL_MODIFICA", sedeVO.getTerminalModifica());
		namedParameters.put("CODIGO", sedeVO.getCode());

		return getNamedParameterJdbcTemplate().update(strSql, namedParameters);
	}

	@Override
	public int insert(SedeVO sedeVO) {
		Map<String, Object> namedParameters = new HashMap<String, Object>();

		String strSql = " INSERT INTO TCS_BEN_SEDE ( CODIGO, NOMBRE, CARACTER, DIRECCION_DESCRIPTIVA,DESDE_VIGENCIA,HASTA_VIGENCIA, "
				+ " VIGENCIA,SEDE_CODIGO,DESCRIPCION,TIPO,DIRECCION_ENCASILLADA,LOCALIZACION_COBAMA,VFL_CODIGO_MUNICIPIO, "
				+ " usuario_crea, fecha_crea, terminal_crea, usuario_modifica, fecha_modifica, terminal_modifica) "
				+ " VALUES ( SCS_BEN_PRG.NEXTVAL, upper(:NOMBRE), upper(:CARACTER), :DIRECCION_DESCRIPTIVA, "
				+ " TO_DATE(:DESDE_VIGENCIA,'dd/mm/yyyy'), TO_DATE(:HASTA_VIGENCIA,'dd/mm/yyyy'),'A', "
				+ " :SEDE_CODIGO, :DESCRIPCION, :TIPO, :DIRECCION_ENCASILLADA, :LOCALIZACION_COBAMA, :VFL_CODIGO_MUNICIPIO, :usuario_crea, TO_DATE(:fecha_crea,'dd/mm/yyyy'), :terminal_crea, :usuario_modifica, TO_DATE(:fecha_modifica,'dd/mm/yyyy'), :terminal_modifica) ";

		namedParameters.put("NOMBRE", sedeVO.getNombre());
		namedParameters.put("CARACTER", sedeVO.getCaracter());
		namedParameters.put("DIRECCION_DESCRIPTIVA",
				sedeVO.getDireccion_descriptiva());
		namedParameters.put("DESDE_VIGENCIA", sedeVO.getDesde());
		namedParameters.put("HASTA_VIGENCIA", sedeVO.getHasta());
		namedParameters.put("SEDE_CODIGO", sedeVO.getCodeSede());
		namedParameters.put("DESCRIPCION", sedeVO.getDescripcion());
		namedParameters.put("TIPO", sedeVO.getTipo());
		namedParameters.put("DIRECCION_ENCASILLADA",
				sedeVO.getDireccion_encasillada());
		namedParameters.put("LOCALIZACION_COBAMA",
				sedeVO.getLocalizacion_cobama());
		namedParameters.put("VFL_CODIGO_MUNICIPIO", sedeVO.getCodeMunicipio());
		namedParameters.put("usuario_crea", sedeVO.getUsuarioCrea());
		namedParameters.put("fecha_crea", sedeVO.getFechaCrea());
		namedParameters.put("terminal_crea", sedeVO.getTerminalCrea());
		namedParameters.put("usuario_modifica", sedeVO.getUsuarioModifica());
		namedParameters.put("fecha_modifica", sedeVO.getFechaModifica());
		namedParameters.put("terminal_modifica", sedeVO.getTerminalModifica());

		return getNamedParameterJdbcTemplate().update(strSql, namedParameters);

	}

	@Override
	public int update(SedeVO sedeVO) {
		Map<String, Object> namedParameters = new HashMap<String, Object>();

		String strSql = " UPDATE TCS_BEN_SEDE SET NOMBRE = :NOMBRE, CARACTER = :CARACTER, "
				+ " DIRECCION_DESCRIPTIVA = :DIRECCION_DESCRIPTIVA, DESDE_VIGENCIA = TO_DATE(:DESDE_VIGENCIA,'dd/mm/yyyy'), "
				+ " VFL_CODIGO_MUNICIPIO = :VFL_CODIGO_MUNICIPIO, HASTA_VIGENCIA = TO_DATE(:HASTA_VIGENCIA,'dd/mm/yyyy'), VIGENCIA = :VIGENCIA, "
				+ " DESCRIPCION = :DESCRIPCION, TIPO = :TIPO, DIRECCION_ENCASILLADA = :DIRECCION_ENCASILLADA, LOCALIZACION_COBAMA = :LOCALIZACION_COBAMA, "
				+ " USUARIO_MODIFICA = :USUARIO_MODIFICA, FECHA_MODIFICA = TO_DATE(:FECHA_MODIFICA,'dd/mm/yyyy'), "
				+ " TERMINAL_MODIFICA = :TERMINAL_MODIFICA WHERE CODIGO = :CODIGO ";

		namedParameters.put("NOMBRE", sedeVO.getNombre());
		namedParameters.put("CARACTER", sedeVO.getCaracter());
		namedParameters.put("DIRECCION_DESCRIPTIVA",
				sedeVO.getDireccion_descriptiva());
		namedParameters.put("DESDE_VIGENCIA", sedeVO.getDesde());
		namedParameters.put("VFL_CODIGO_MUNICIPIO", sedeVO.getCodeMunicipio());
		namedParameters.put("HASTA_VIGENCIA", sedeVO.getHasta());
		namedParameters.put("VIGENCIA", sedeVO.getVigencia());
		namedParameters.put("DESCRIPCION", sedeVO.getDescripcion());
		namedParameters.put("TIPO", sedeVO.getTipo());
		namedParameters.put("DIRECCION_ENCASILLADA",
				sedeVO.getDireccion_encasillada());
		namedParameters.put("LOCALIZACION_COBAMA",
				sedeVO.getLocalizacion_cobama());
		namedParameters.put("USUARIO_MODIFICA", sedeVO.getUsuarioModifica());
		namedParameters.put("FECHA_MODIFICA", sedeVO.getFechaModifica());
		namedParameters.put("TERMINAL_MODIFICA", sedeVO.getTerminalModifica());
		namedParameters.put("CODIGO", sedeVO.getCode());

		return getNamedParameterJdbcTemplate().update(strSql, namedParameters);
	}

}
